其他
WOW怀旧服 明文发包获取和HOOK
看雪论坛作者ID:Kaining
1
找出什么通过什么函数发包 send sendto WSASend
2
判断是否为线程发包
喊话 断下
地址 返回到 返回自 大小 注释 方
000000000012D808 000000014160FF9D 000007FEFF348000 C0 ws2_32.000007FEFF348000 用户模块
000000000012D8C8 0000000141610394 000000014160FF9D 50 wowclassic.000000014160FF9D 用户模块
000000000012D918 0000000141627E5F 0000000141610394 140 wowclassic.0000000141610394 用户模块
000000000012DA58 0000000141610759 0000000141627E5F 30 wowclassic.0000000141627E5F 用户模块
000000000012DA88 0000000140A3561B 0000000141610759 90 wowclassic.0000000141610759 用户模块
000000000012DB18 0000000140A356E0 0000000140A3561B 50 wowclassic.0000000140A3561B 用户模块
000000000012DB68 0000000140F4EF7E 0000000140A356E0 510 wowclassic.0000000140A356E0 用户模块
000000000012E078 0000000140F3147B 0000000140F4EF7E 1100 wowclassic.0000000140F4EF7E 用户模块
000000000012F178 0000000141996779 0000000140F3147B 40 wowclassic.0000000140F3147B 用户模块
000000000012F1B8 000000014199A063 0000000141996779 130 wowclassic.0000000141996779 用户模块
000000000012F2E8 00000001419960AF 000000014199A063 40 wowclassic.000000014199A063 用户模块
000000000012F328 0000000141989707 00000001419960AF 30 wowclassic.00000001419960AF 用户模块
000000000012F358 0000000141996D03 0000000141989707 150 wowclassic.0000000141989707 用户模块
000000000012F4A8 000000014199627E 0000000141996D03 50 wowclassic.0000000141996D03 用户模块
000000000012F4F8 000000014198AB74 000000014199627E 50 wowclassic.000000014199627E 用户模块
000000000012F548 00000001403A8E6C 000000014198AB74 70 wowclassic.000000014198AB74 用户模块
000000000012F5B8 00000001402ED8C2 00000001403A8E6C 60 wowclassic.00000001403A8E6C 用户模块
000000000012F618 0000000141CD873E 00000001402ED8C2 70 wowclassic.00000001402ED8C2 用户模块
000000000012F688 00000001402E8763 0000000141CD873E F0 wowclassic.0000000141CD873E 用户模块
000000000012F778 00000001402C3C06 00000001402E8763 60 wowclassic.00000001402E8763 用户模块
000000000012F7D8 00000001402C3677 00000001402C3C06 90 wowclassic.00000001402C3C06 用户模块
000000000012F868 0000000140A3E840 00000001402C3677 40 wowclassic.00000001402C3677 用户模块
000000000012F8A8 0000000140A3E3F5 0000000140A3E840 50 wowclassic.0000000140A3E840 用户模块
000000000012F8F8 0000000140A3F79A 0000000140A3E3F5 C0 wowclassic.0000000140A3E3F5 用户模块
000000000012F9B8 0000000140A3F16F 0000000140A3F79A 30 wowclassic.0000000140A3F79A 用户模块
000000000012F9E8 000000014046E7FA 0000000140A3F16F 200 wowclassic.0000000140A3F16F 用户模块
000000000012FBE8 0000000077569BD1 000000014046E7FA C0 wowclassic.000000014046E7FA 系统模块
000000000012FCA8 00000000775698DA 0000000077569BD1 80 user32.0000000077569BD1 系统模块
000000000012FD28 0000000140A3E9F5 00000000775698DA C0 user32.00000000775698DA 用户模块
000000000012FDE8 00000001402C2C83 0000000140A3E9F5 50 wowclassic.0000000140A3E9F5 用户模块
000000000012FE38 00000001402C26DC 00000001402C2C83 30 wowclassic.00000001402C2C83 用户模块
000000000012FE68 000000014019C9AA 00000001402C26DC 50 wowclassic.00000001402C26DC 用户模块
000000000012FEB8 00000001401AD6FA 000000014019C9AA 30 wowclassic.000000014019C9AA 用户模块
000000000012FEE8 00000001401AD71B 00000001401AD6FA 30 wowclassic.00000001401AD6FA 用户模块
000000000012FF18 0000000141AD69D6 00000001401AD71B 40 wowclassic.00000001401AD71B 用户模块
000000000012FF58 000000007744652D 0000000141AD69D6 30 wowclassic.0000000141AD69D6 系统模块
000000000012FF88 000000007767C521 000000007744652D 50 kernel32.000000007744652D 系统模块
000000000012FFD8 0000000000000000 000000007767C521 ntdll.000000007767C521 用户模块
点击登录触发
地址 返回到 返回自 大小 注释 方
000000000012ED18 000000014160FF9D 000007FEFE438000 C0 ws2_32.000007FEFE438000 用户模块
000000000012EDD8 0000000141610394 000000014160FF9D 50 wowclassic.000000014160FF9D 用户模块
000000000012EE28 0000000141627E5F 0000000141610394 140 wowclassic.0000000141610394 用户模块
000000000012EF68 0000000141610759 0000000141627E5F 30 wowclassic.0000000141627E5F 用户模块
000000000012EF98 0000000140A3561B 0000000141610759 90 wowclassic.0000000141610759 用户模块
000000000012F028 0000000140A356E0 0000000140A3561B 50 wowclassic.0000000140A3561B 用户模块
000000000012F078 00000001401A54C6 0000000140A356E0 70 wowclassic.0000000140A356E0 用户模块
000000000012F0E8 0000000140405CDF 00000001401A54C6 90 wowclassic.00000001401A54C6 用户模块
000000000012F178 000000014042DD2E 0000000140405CDF 30 wowclassic.0000000140405CDF 用户模块
000000000012F1A8 0000000141996779 000000014042DD2E 40 wowclassic.000000014042DD2E 用户模块
000000000012F1E8 000000014199A063 0000000141996779 130 wowclassic.0000000141996779 用户模块
000000000012F318 00000001419960AF 000000014199A063 40 wowclassic.000000014199A063 用户模块
000000000012F358 0000000141989707 00000001419960AF 30 wowclassic.00000001419960AF 用户模块
000000000012F388 0000000141996D03 0000000141989707 150 wowclassic.0000000141989707 用户模块
000000000012F4D8 000000014199627E 0000000141996D03 50 wowclassic.0000000141996D03 用户模块
000000000012F528 000000014198AB74 000000014199627E 50 wowclassic.000000014199627E 用户模块
000000000012F578 00000001403A8E6C 000000014198AB74 70 wowclassic.000000014198AB74 用户模块
000000000012F5E8 0000000141CCE456 00000001403A8E6C 60 wowclassic.00000001403A8E6C 用户模块
000000000012F648 0000000141CCF1B8 0000000141CCE456 30 wowclassic.0000000141CCE456 用户模块
000000000012F678 0000000141CCF743 0000000141CCF1B8 30 wowclassic.0000000141CCF1B8 用户模块
000000000012F6A8 00000001402E93A4 0000000141CCF743 80 wowclassic.0000000141CCF743 用户模块
000000000012F728 00000001402C3C06 00000001402E93A4 60 wowclassic.00000001402E93A4 用户模块
000000000012F788 00000001402C33CA 00000001402C3C06 60 wowclassic.00000001402C3C06 用户模块
000000000012F7E8 00000001402C38AB 00000001402C33CA 90 wowclassic.00000001402C33CA 用户模块
000000000012F878 0000000140A3E840 00000001402C38AB 40 wowclassic.00000001402C38AB 用户模块
000000000012F8B8 0000000140A3DF97 0000000140A3E840 40 wowclassic.0000000140A3E840 用户模块
000000000012F8F8 0000000140A3FB07 0000000140A3DF97 C0 wowclassic.0000000140A3DF97 用户模块
000000000012F9B8 0000000140A3F16F 0000000140A3FB07 30 wowclassic.0000000140A3FB07 用户模块
000000000012F9E8 000000014046E7FA 0000000140A3F16F 200 wowclassic.0000000140A3F16F 用户模块
000000000012FBE8 0000000076F39BD1 000000014046E7FA C0 wowclassic.000000014046E7FA 系统模块
000000000012FCA8 0000000076F398DA 0000000076F39BD1 80 user32.0000000076F39BD1 系统模块
000000000012FD28 0000000140A3E9F5 0000000076F398DA C0 user32.0000000076F398DA 用户模块
000000000012FDE8 00000001402C2C83 0000000140A3E9F5 50 wowclassic.0000000140A3E9F5 用户模块
000000000012FE38 00000001402C26DC 00000001402C2C83 30 wowclassic.00000001402C2C83 用户模块
000000000012FE68 000000014019C9AA 00000001402C26DC 50 wowclassic.00000001402C26DC 用户模块
000000000012FEB8 00000001401AD6FA 000000014019C9AA 30 wowclassic.000000014019C9AA 用户模块
000000000012FEE8 00000001401AD71B 00000001401AD6FA 30 wowclassic.00000001401AD6FA 用户模块
000000000012FF18 0000000141AD69D6 00000001401AD71B 40 wowclassic.00000001401AD71B 用户模块
000000000012FF58 000000007703652D 0000000141AD69D6 30 wowclassic.0000000141AD69D6 系统模块
000000000012FF88 000000007716C521 000000007703652D 50 kernel32.000000007703652D 系统模块
000000000012FFD8 0000000000000000 000000007716C521 ntdll.000000007716C521 用户模块
0000000141636FC0 | 48:8BD1 | mov rdx,rcx | rcx:"th"
0000000141636FC3 | 48:8B0D A62C3601 | mov rcx,qword ptr ds:[142999C70] | rcx:"th"
0000000141636FCA | 48:85C9 | test rcx,rcx | rcx:"th"
0000000141636FCD | 74 0B | je wowclassic.141636FDA |
0000000141636FCF | 41:B8 02000000 | mov r8d,2 |
0000000141636FD5 | E9 96E63FFF | jmp wowclassic.140A35670 |
0000000141636FDA | C3 | ret |
3
追出包地址和包长及加密过程
000000014160FF97 FF15 13228D00 call qword ptr ds:[141EE21B0] 发包CALL 0
000000014161038F E8 8CFBFFFF call wowclassic.14160FF20 发包CALL 00
0000000141627E5A E8 61AFFEFF call wowclassic.141612DC0 发包CALL 000
0000000141610756 FF50 08 call qword ptr ds:[rax+8] 发包CALL 0000
0000000140A35616 E8 C5B0BD00 call wowclassic.1416106E0 发包CALL 00000
0000000140A356DB E8 20FDFFFF call wowclassic.140A35400 发包CALL 000000
0000000140BF1E24 E8 9751A400 call wowclassic.141636FC0 发包CALL 0000000
我们从第一个开始看,知道rdx是包地址,r8就是长度,我们都追下。
000000014160FF8E | 45:33C9 | xor r9d,r9d |
000000014160FF91 | 44:8BC5 | mov r8d,ebp |
000000014160FF94 | 49:8BD6 | mov rdx,r14 | r14 包长 ebp 包长
000000014160FF72 | 4C:8B32 | mov r14,qword ptr ds:[rdx] | [rdx] 包长 ebp 包长
000000014160FF2B | 8B6A 10 | mov ebp,dword ptr ds:[rdx+10] | [rdx] 包长 [rdx+10] 包长
0000000141610389 | 48:8BD7 | mov rdx,rdi | [rdi] 包长 [rdi+10] 包长
0000000141610365 | 48:8BFA | mov rdi,rdx | [rdx] 包长 [rdx+10] 包长
0000000141627E54 | 49:8BD7 | mov rdx,r15 | [r15] 包长 [r15+10] 包长
0000000141627CD0 | 4C:8D7C24 20 | lea r15,qword ptr ss:[rsp+20] | [rsp+20] 包长 [rsp+20+10] 包长 这里只给了地址 里面是空的
0000000141627D00 | 41:890408 | mov dword ptr ds:[r8+rcx],eax | 这里给包长赋值
0000000141627D00 | 41:890408 | mov dword ptr ds:[r8+rcx],eax | 这里给包长赋值
0000000141627D3B | 8918 | mov dword ptr ds:[rax],ebx | 这里把我们原来的包长给前四个字节
0000000141627DA1 | E8 BA754100 | call wowclassic.141A3F360 | 加密包体
0000000141627DF4 | F241:0F114424 04 | movsd qword ptr ds:[r12+4],xmm0 | 改变包头+4 到 +B位置的这8个字节
0000000141627E4F | 41:894424 0C | mov dword ptr ds:[r12+C],eax | 这里改变了 包头+C 到 +F位置的字节
0000000141627DE3 | E8 A8824100 | call wowclassic.141A40090 | 生成包头4-F 这13个字节需要的值 存放于rbp+10的前C个字节
首先我们获取到一个明文包内容,但是里面不全部是我们的内容。长度也是加密长度,经过一个CALL后,我们包长+10,这时候这+10字节是我们的包头。
然后给我们的包头前4个字节,我们的加密包长,经过这个加密包长给我们原来的包进行一个CALL里面加密(俗称包体加密CALL)。
然后继续给包头+4到+F位置进行赋值,这个值是来自己上面这个给CALL的 rbp+10里面,因为这个CALL的参数里面有一个是rbp+10的地址。
经过这个CALL之后这里面的值改变了。
4
最内层明文封包CALL分析
000000000014D9C0 00000000233A7F80 ..:#....
000000000014D9C8 0000000000000000 ........
000000000014D9D0 0000001000000012 ........
00000000233A7F80 00050000000737E7 ç7......
00000000233A7F88 3837363534333231 12345678
00000000233A7F90 0000000000003039 90......
可以看到 长度 12 就是我们发送的数据结尾 到30我们发的数据就是1234567890 就说明 这个12是总包长 然后我们现在不知道就是 00050000000737E7 这写是什么 我们在发个包看看
000000000014D9C0 0000000021D58320 .Õ!....
000000000014D9C8 0000000000000000 ........
000000000014D9D0 0000001000000018 ........
0000000021D58320 00080000000737E7 ç7......
0000000021D58328 3131313131313131 11111111
0000000021D58330 3131313131313131 11111111
可以看到 变成了 00080000000737E7 我们基本可以判断 0000000737E7 是相等的 那么为什么是后2字节是0008和0005呢 我们看下
第一次 我们发送1234567890 10长度 是5
第二次 我们发送1111111111111111 16长度 是8
看似是我们长度的一半 我们去构建一个 试试
00060000000737E7
3131313131313131
31313131
发送12个1 看看我们的看看我们的额包内容是不是这个
000000001FEB1C40 80060000000737E7 ç7......
000000001FEB1C48 3131313131313131 11111111
000000001FEB1C50 0000003131313131 11111...
发现 其他没什么变换 就是最后一个字节 从 00 变成了80
经过我们多次的设计和测试 发现 /2 整除是00 有余是80 也就是我们发送的包长奇数是80 偶数是00
000000014166C7EC | 48:8B8B E0000000 | mov rcx,qword ptr ds:[rbx+E0] | 参数1 [rbx+E0]
000000014166C7AC | 48:8BD9 | mov rbx,rcx | 参数1 [rcx+E0]
0000000140A69000 | 48:8B8CFB 90010000 | mov rcx,qword ptr ds:[rbx+rdi*8+190] | 参数1 [[rbx+rdi*8+0x190]+E0]
测试了rdi == 0
0000000140A68E28 | 48:8BD9 | mov rbx,rcx | 参数1 [[rcx+rdi*8+0x190]+E0]
0000000140A690E8 | 48:8BCE | mov rcx,rsi | 参数1 [[rsi+rdi*8+0x190]+E0]
0000000140A690A8 | 48:8BF1 | mov rsi,rcx | 参数1 [[rcx+rdi*8+0x190]+E0]
0000000141693073 | 48:8B0D F63B3601 | mov rcx,qword ptr ds:[1429F6C70] | 参数1 [[[0x00000001429F6C70]+rdi*8+0x190]+E0]
0000000141693073 | 48:8B0D F63B3601 | mov rcx,qword ptr ds:[1429F6C70] | 参数1 [[[wowclassic.exe + 0x29F6C70]+rdi*8+0x190]+E0]
void CDLG_MAIN::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
BYTE b_packet[18] = {0xE7, 0X37, 0X07, 0X00, 0X00, 0X00, 0X05, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 };
DWORD dw_temp_array[6] = { 0, 0, 0, 0, 0x12, 0x10 };
*(QWORD*)dw_temp_array = (QWORD)b_packet;
QWORD qw_rdx = (QWORD)dw_temp_array;
fun_send_call(base_send, qw_rdx, 1);
}
__declspec(naked) void fun_send_call(QWORD qw_rcx,QWORD qw_rdx,DWORD dw_r8d)
{
__asm
{
push rax
sub rsp, 0x100
add rcx, base_module_base
mov rcx, [rcx]
add rcx, offset_send_one
mov rcx, [rcx]
add rcx, offset_send_two
mov rcx, [rcx]
mov rax, [rcx]
add rax, 0x8
mov rax, [rax]
call rax
add rsp, 0x100
pop rax
retn
}
}
5
Hook send函数
void CDLG_MAIN::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
fun_hook_send();
}
void CDLG_MAIN::OnBnClickedButton4()
{
// TODO: 在此添加控件通知处理程序代码
fun_reduction_send();
}
void fun_hook_send()
{
g_hook_send = new CInlineHook((__int64)send, (__int64)fun_send_proc,false,15);
g_hook_send->MotifyAddress();
}
void fun_reduction_send()
{
g_hook_send->RestoreAddress();
delete g_hook_send;
g_hook_send = nullptr;
}
// __int64 fun_send_proc_jmp = ((__int64)send + 15);
void fun_send_proc()
{
/*
00007FFDDDC21210 | 48:895C24 08 | mov qword ptr ss:[rsp+8],rbx | [rsp+8]:&"P#F凖\x7F"
00007FFDDDC21215 | 48:896C24 10 | mov qword ptr ss:[rsp+10],rbp |
00007FFDDDC2121A | 48:897424 18 | mov qword ptr ss:[rsp+18],rsi |
*/
// 这里如果是CALL进来的 rsp要+8 所以后面每个都要+8
__asm
{
mov qword ptr ss : [rsp + 0x10], rbx
mov qword ptr ss : [rsp + 0x18], rbp
mov qword ptr ss : [rsp + 0x20], rsi
retn
}
}
HOOK类
CInlineHook.h
#pragma once
#include <windows.h>
#include <stdio.h>
class CInlineHook
{
private:
#ifndef _WIN64
using uchar = unsigned char;
uchar* m_cOriginalByte; //原始OPCODE
uchar* m_cMyByte; //自己的OPCODE
int m_nOriginalAddress; //原始地址
int m_nMyAddress; //自己的函数地址
int m_nHookLen;
DWORD MotifyMemProtect(int nAddress,DWORD dwProtect = PAGE_EXECUTE_READWRITE);
#else
using uchar = unsigned char;
uchar* m_cOriginalByte; //原始OPCODE
uchar* m_cMyByte; //自己的OPCODE
__int64 m_nOriginalAddress; //原始地址
__int64 m_nMyAddress; //自己的函数地址
int m_nHookLen;
DWORD MotifyMemProtect(__int64 nAddress, DWORD dwProtect = PAGE_EXECUTE_READWRITE);
#endif
public:
#ifndef _WIN64
// bPattern true 为jmp false 为call
CInlineHook(int nOriginalAddress, int nMyAddress, bool bPattern = true, int nHookLen = 5);
#else
// bPattern true 为jmp false 为call
CInlineHook(__int64 nOriginalAddress, __int64 nMyAddress, bool bPattern = true, int nHookLen = 12);
#endif
void MotifyAddress();
void RestoreAddress();
~CInlineHook();
};
CInlineHook.cpp
#include "pch.h"
#include "CInlineHook.h"
CInlineHook::~CInlineHook()
{
delete[] m_cMyByte;
m_cMyByte = nullptr;
delete[] m_cOriginalByte;
m_cOriginalByte = nullptr;
}
void CInlineHook::MotifyAddress()
{
DWORD dwProtect = MotifyMemProtect(m_nOriginalAddress);
memcpy(reinterpret_cast<void*>(m_nOriginalAddress), m_cMyByte, m_nHookLen);
MotifyMemProtect(m_nOriginalAddress, dwProtect);
}
void CInlineHook::RestoreAddress()
{
DWORD dwProtect = MotifyMemProtect(m_nOriginalAddress);
memcpy(reinterpret_cast<void*>(m_nOriginalAddress), m_cOriginalByte, m_nHookLen);
MotifyMemProtect(m_nOriginalAddress, dwProtect);
}
#ifndef _WIN64
DWORD CInlineHook::MotifyMemProtect(int nAddress, DWORD dwProtect)
{
DWORD dwOldProtect;
VirtualProtect(reinterpret_cast<void*>(nAddress), m_nHookLen, dwProtect, &dwOldProtect);
return dwOldProtect;
}
CInlineHook::CInlineHook(int nOriginalAddress, int nMyAddress, bool bPattern, int nHookLen)
:m_nOriginalAddress(nOriginalAddress), m_nMyAddress(nMyAddress), m_nHookLen(nHookLen)
{
m_cMyByte = new uchar[nHookLen];
m_cOriginalByte = new uchar[nHookLen];
if (bPattern)
{
m_cMyByte[0] = '\xE9';
}
else
{
m_cMyByte[0] = '\xE8';
}
int nOffset = nMyAddress - (nOriginalAddress + 5);
memcpy(&m_cMyByte[1], &nOffset, 4);
for (int i = 0; i < nHookLen - 5; i++) {
m_cMyByte[i + 5] = '\x90';
}
DWORD dwProtect = MotifyMemProtect(nOriginalAddress);
memcpy(m_cOriginalByte, reinterpret_cast<void*>(nOriginalAddress), m_nHookLen);
MotifyMemProtect(nOriginalAddress, dwProtect);
}
#else
DWORD CInlineHook::MotifyMemProtect(__int64 nAddress, DWORD dwProtect /*= PAGE_EXECUTE_READWRITE*/)
{
DWORD dwOldProtect;
VirtualProtect(reinterpret_cast<void*>(nAddress), m_nHookLen, dwProtect, &dwOldProtect);
return dwOldProtect;
}
CInlineHook::CInlineHook(__int64 nOriginalAddress, __int64 nMyAddress, bool bPattern /*= true*/, int nHookLen /*= 12*/)
:m_nOriginalAddress(nOriginalAddress), m_nMyAddress(nMyAddress), m_nHookLen(nHookLen)
{
m_cMyByte = new uchar[nHookLen];
m_cOriginalByte = new uchar[nHookLen];
m_cMyByte[0] = '\x48';
m_cMyByte[1] = '\xB8';
memcpy(&m_cMyByte[2], &nMyAddress,8);
m_cMyByte[10] = '\xFF';
if (bPattern)
{
m_cMyByte[11] = '\xE0';
}
else
{
m_cMyByte[11] = '\xD0';
}
if (nHookLen > 12)
{
for (int i = 12; i < nHookLen; i++)
{
m_cMyByte[i] = '\x90';
}
}
DWORD dwProtect = MotifyMemProtect(nOriginalAddress);
memcpy(m_cOriginalByte, reinterpret_cast<void*>(nOriginalAddress), m_nHookLen);
MotifyMemProtect(nOriginalAddress, dwProtect);
}
#endif
6
000000000014D958 000000014166C809 返回到 wowclassic.000000014166C809 自 ???
000000000014D960 00000000005688A0
000000000014D968 0000000000000001
000000000014D970 0000000000568AB0
000000000014D978 0000000000000012
000000000014D980 000000000056D680
000000000014D988 0000000140A6902B 返回到 wowclassic.0000000140A6902B 自 wowclassic.000000014166C790
000000000014D990 0000000000000000
000000000014D998 000000000056D610
000000000014D9A0 0000000000000000
000000000014D9A8 00000001404A31BD 返回到 wowclassic.00000001404A31BD 自 wowclassic.00000001401C9940
000000000014D9B0 000000000014DA00
000000000014D9B8 000000000014DA54
000000000014D9C0 000000002405CC60
000000000014D9C8 0000000000000000
000000000014D9D0 0000001000000012
000000000014D9D8 0000000100000000
000000000014D9E0 0000000000000000
000000000014D9E8 0000000000000000
000000000014D9F0 00000000335B08C0 &"@灚@\x01"
000000000014D9F8 0000000000000000
000000000014DA00 0000000000000002
000000000014DA08 000000000056D610
000000000014DA10 0000000141F55DC0 wowclassic.0000000141F55DC0
000000000014DA18 0000000140A690F0 返回到 wowclassic.0000000140A690F0 自 wowclassic.0000000140A68E10
喊话断下 也是这里 我们给他记录下
0x140A690F0 == wowclassic.exe + 0xA690F0
void fun_send_proc()
{
/*
00007FFDDDC21210 | 48:895C24 08 | mov qword ptr ss:[rsp+8],rbx | [rsp+8]:&"P#F凖\x7F"
00007FFDDDC21215 | 48:896C24 10 | mov qword ptr ss:[rsp+10],rbp |
00007FFDDDC2121A | 48:897424 18 | mov qword ptr ss:[rsp+18],rsi |
*/
// 这里如果是CALL进来的 rsp要+8 所以后面每个都要+8
__asm
{
push rax
; 这里因为push了 所以 + 0x310变成了 + 0x318
mov rax, [rsp + 0x318]
mov hook_send_rsp_cmp, rax
; +0x320里面存放的就是数据
mov rax, [rsp + 0x328]
mov get_hook_send_packet, rax
mov get_hook_send_len, r8
pop rax
}
// 这里如果相等就说明是功能明文包 不然就心跳包 直接过滤
get_hook_send_rsp_0x310 = (__int64)base_module_base + base_hook_send_rsp_0x310;
if (hook_send_rsp_cmp == get_hook_send_rsp_0x310)
{
__asm
{
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
sub rsp,0x100
}
fun_out_packet_text();
__asm
{
add rsp,0x100
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
}
}
__asm
{
mov qword ptr ss : [rsp + 0x8], rbx
mov qword ptr ss : [rsp + 0x10], rbp
mov qword ptr ss : [rsp + 0x18], rsi
jmp fun_send_proc_jmp
}
}
void fun_hook_send()
{
g_hook_send = new CInlineHook((__int64)send, (__int64)fun_send_proc,true,15);
g_hook_send->MotifyAddress();
}
void fun_reduction_send()
{
g_hook_send->RestoreAddress();
delete g_hook_send;
g_hook_send = nullptr;
}
void fun_out_packet_text()
{
printf("长度:%d", get_hook_send_len);
byte *ptr = 0;
char str_temp[0x2000];
char str_out[0x2000] = "";
for (__int64 i = 0; i < get_hook_send_len; i++)
{
sprintf_s(str_temp, "%02X", *(byte*)(get_hook_send_packet + i));
strcat_s(str_out, str_temp);
}
printf("\t\t\t明文包内容:%s\r\n", str_out);
delete ptr;
if (ptr != nullptr)
{
ptr = nullptr;
}
}
我们这里已经能正确输出所有的功能CALL的函数了
7
0000000140A690EB | E8 20FDFFFF | call wowclassic.140A68E10 | 最外层明文包
000000014166C806 | FF50 08 | call qword ptr ds:[rax+8] | 最内层明文包
000000000014DAE0 0000000142185CE8 è\.B.... "@刅@\x01"
000000000014DAE8 8000001200000000 ........
000000000014DAF0 0000000000000000 ........
000000000014DAF8 0000000000000000 ........
000000000014DB00 3131313100000007 ....1111
000000000014DB08 0000313131313131 111111..
包地址里面是这样的
00000000310D4390 00000000310D3E90 .>.1.... &"怑\r1"
00000000310D4398 FFFF000142591BE0 à.YB..ÿÿ
00000000310D43A0 00050000000737E7 ç7......
00000000310D43A8 3131313131313131 11111111
00000000310D43B0 0000000000003131 11......
0000000021FB6710 00050000000737E7 ç7......
0000000021FB6718 3131313131313131 11111111
0000000021FB6720 0000000000003131 11......
0000000140A690CA | 48:8B03 | mov rax,qword ptr ds:[rbx] |
0000000140A690CD | 48:8D5424 20 | lea rdx,qword ptr ss:[rsp+20] |
0000000140A690D2 | 48:8BCB | mov rcx,rbx |
0000000140A690D5 | FF50 10 | call qword ptr ds:[rax+10] | 这个CALL 讲内容转换成了 最内层的明文包
可以看出 这个CALL就是只有 两个参数 rcx和rdx 还有一个CALL rax rax来自 rbx rcx来自rbx 也就是 我们只要找处 rbx和rdx即可
000000000014DA40 0000000141F55DC0 À]õA.... wowclassic.0000000141F55DC0
000000000014DA48 0000000022218F10 ..!"....
000000000014DA50 0000010000000000 ........
000000000014DA58 FFFFFFFF00000010 ....ÿÿÿÿ
000000000014DA60 0000000000000001 ........
可以看到 +0 就是个 基址 wowclassic.exe + 0x1F55DC0
+8 看似是个申请出来的地址 每次都会变 存放的就是 下面第一张图
+10 是个固定的值0000010000000000
+18 运行CALL 之后被填入长度
+20 就是一个固定的1
8
// 明文解析 解析0x320处的明文封包解析成最外层明文封包
__declspec(naked) void fun_plaintext_parsing(QWORD qw_rcx, QWORD qw_rdx)
{
/*
0000000140A690CA | 48:8B03 | mov rax,qword ptr ds:[rbx] |
0000000140A690CD | 48:8D5424 20 | lea rdx,qword ptr ss:[rsp+20] |
0000000140A690D2 | 48:8BCB | mov rcx,rbx |
0000000140A690D5 | FF50 10 | call qword ptr ds:[rax+10] | 这个CALL 讲内容转换成了 最内层的明文包
*/
__asm
{
push rax
sub rsp,0x100
mov rax, get_hook_send_packet
mov rax, [rax]
add rax, 0x10
call[rax]
add rsp, 0x100
pop rax
retn
}
}
void fun_out_packet_text()
{
QWORD qw_rdx;
QWORD qw_rcx = get_hook_send_packet;
QWORD qw_one = (__int64)base_module_base + base_packet_to_call_stc_address;
BYTE* ptr_packet = new BYTE[100];
QWORD qw_stc[5] = { qw_one,(QWORD)ptr_packet,0x0000010000000000,0xFFFFFFFF00000010,1 };
qw_rdx = (QWORD)&qw_stc;
//printf("rcx == %I64d", &qw_rcx);
//printf("rdx == %I64d", &qw_rdx);
fun_plaintext_parsing(qw_rcx, qw_rdx);
byte *ptr = 0;
char str_temp[0x2000] = "";
char str_out[0x2000] = "";
DWORD dw_len = (DWORD)qw_stc[3];
printf("长度:%d", dw_len - 0x10);
QWORD qw_address = qw_stc[1] + 0x10; // 获取存取明文包地址
for (__int64 i = 0; i < dw_len - 0x10; i++)
{
//printf("地址 == %I64d", qw_address + i);
sprintf_s(str_temp, "%02X", *(byte*)(qw_address + i));
strcat_s(str_out, str_temp);
}
printf("\t\t\t明文包内容:%s\r\n", str_out);
delete ptr;
delete ptr_packet;
if (ptr != nullptr)
{
ptr = nullptr;
}
if (ptr_packet != nullptr)
{
ptr_packet = nullptr;
}
}
看雪ID:Kaining
https://bbs.pediy.com/user-home-846211.htm
*本文由看雪论坛 Kaining 原创,转载请注明来自看雪社区
# 往期推荐
2. 新的漏洞分析体验:CVE-2010-3333 RTF栈缓冲区溢出漏洞
5. angr学习(三)一道自己模仿着出的简单题和angr-ctf符号化输入相关题目
球分享
球点赞
球在看
点击“阅读原文”,了解更多!